home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Languages / Masm V6.11 / INCLUDE / CMACROS.IN$ / CMACROS.bin
Encoding:
Text File  |  1993-09-16  |  44.4 KB  |  2,029 lines

  1. comment $
  2. cmacros - assembly macros for interfacing to hhls
  3. (C)Copyright Microsoft Corp. 1984-1993
  4. $
  5.  
  6. .xcref
  7. ??CM_Paste macro arg1:req, arg2:req
  8. exitm <arg1&arg2>
  9. endm
  10.  
  11. ;    ??_out    - output given message to the console unless ?QUIET has
  12. ;    been specified.
  13. ;
  14. ;    usage:
  15. ;        ??_out    <t>
  16. ;
  17. ;    where:
  18. ;        <t> is the message to output
  19. .xcref ??_out
  20. ??_out macro t
  21. ifndef ?QUIET
  22. %out t
  23. endif
  24. endm
  25.  
  26. ;    outif - output msg if name is non-zero.  if name is undefined,
  27. ;    set name = 0, else set name to the default value.
  28. ;
  29. ;    usage:
  30. ;        outif    name,defval,onmsg,offmsg
  31. ;    where:
  32. ;        name    name of symbol
  33. ;        defval    default value to give symbol if not defined
  34. ;            if blank, then 0 will be used
  35. ;        onmsg    text to display if symbol is non-zero
  36. ;        offmsg    test to be displayed if symbol is zero
  37.  
  38. outif macro name,defval,onmsg,offmsg
  39. ifndef name
  40. ifb <defval>
  41. name=0
  42. else
  43. name=defval
  44. endif
  45. endif
  46. if name
  47. name=1
  48. ifnb <onmsg>
  49. ??_out <! onmsg>
  50. endif
  51. else
  52. ifnb <offmsg>
  53. ??_out <! offmsg>
  54. endif
  55. endif
  56. endm
  57.  
  58. ;    ??error - output msg and generate an assembly time error
  59. ;
  60. ;    usage:
  61. ;        ??error <t>
  62. ;    where:
  63. ;        t    is the text to be output
  64.  
  65. .xcref ??error
  66. ??error macro msg
  67. %out e r r o r ----- msg
  68. .err e r r o r ----- msg
  69. endm
  70. .xcref ASMpass
  71. .xcref memS,memM,memL,memC,memH,memMOD,sizec,sized
  72. ASMpass=1
  73. ifdef ?SMALL
  74. memS=1
  75. endif
  76. ifdef ?MEDIUM
  77. memM=1
  78. endif
  79. ifdef ?COMPACT
  80. memC=1
  81. endif
  82. ifdef ?LARGE
  83. memL=1
  84. endif
  85. ifdef ?HUGE
  86. memH=1
  87. endif
  88. ??_out <cMacros Version 5.32 - Copyright (c) Microsoft Corp. 1984-1993>
  89. outif memS,0,<Small Model>
  90. outif memM,0,<Medium Model>
  91. outif memL,0,<Large Model>
  92. outif memC,0,<Compact Model>
  93. outif memH,0,<Huge Model>
  94. memMOD= memS + memM + memL + memC + memH
  95. if memMOD ne 1
  96. if memMOD eq 0
  97. memS = 1
  98. outif memS,0,<Small Model>
  99. else
  100. ??error <more than 1 memory model selected>
  101. endif
  102. endif
  103. sizec= memM + memL + memH
  104. sized= memL + memC + (memH*2)
  105. outif ?DF,0,<No segments or groups will be defined>
  106. outif ?TF,0,<Epilog sequences assume valid SP>
  107. outif ?WIN,1,<Windows support>
  108. if ?WIN eq 1
  109. outif ?PLM,1,<>
  110. else
  111. outif ?PLM,1,<PL/M calling convention>
  112. endif
  113. ifndef ?NODATA
  114. ?nodata1=0
  115. else
  116. ?nodata1=1
  117. ??_out <! NODATA module>
  118. endif
  119. ifndef ?CHKSTK
  120. ?chkstk1=0
  121. else
  122. ?chkstk1=1
  123. ifdef ?CHKSTKPROC
  124. ??_out <! Private stack checking enabled>
  125. else
  126. ??_out <! Stack checking enabled>
  127. endif
  128. endif
  129. ifndef DOS5
  130. ?DOS5=0
  131. else
  132. ?DOS5=1
  133. ??_out <! DOS5 module>
  134. endif
  135. ifdef ?PROFILE
  136. ??_out <! Native profiling enabled>
  137. endif
  138. ;;    Initialize all symbols used in the macros.  Theses symbols will not be
  139. ;;      included in any cross reference listing.
  140. .xcref ?n,?ax,?ah,?al,?bx,?bh
  141. .xcref ?bl,?cx,?ch,?cl,?dx,?dh
  142. .xcref ?dl,?si,?di,?es,?ds,?bp
  143. .xcref ?sp,?ss,?cs
  144. .xcref ?rsl,?cpd,?argl,?argc,?ba
  145. .xcref ?acb,???,?po
  146. .xcref ?pas,?pc
  147. .xcref uconcat,mpush,mpop
  148. .xcref ?ri,?pp,?pp1,?al1
  149. .xcref ?ad,?ap,?atal,?dd,?dd1,?dd2
  150. .xcref ?pg,?pg1,?aloc,?cs1,?cs2
  151. .xcref ?DF,?TF,?ff,?PLM,?WIN,?ia,?pu,?adj
  152. .xcref ?uf,?rp,?nx,?nd,?nodata1,?chkstk1,?DOS5
  153. .xcref ?wfp,arg,cCall,cProc,assumes,?cs3,?cs2,?cs1
  154. .xcref defgrp,addseg,createSeg
  155. .xcref save,outif,errnz,errn$,errnz1
  156. .xcref ?PLMPrevParm,?gcc
  157. .xcref ?cCall1,?pcc
  158. ?rsl    =       0           ;;0 = no register to save
  159. ?cpd    =       0           ;;<> 0 if in a procedure definition
  160. ?argl   =       0           ;;length of arguments pushed on stack
  161. ?argc   =       0           ;;# of arguments so far
  162. ?ba     =       0           ;;<>0 if in a procedure (xbegin)
  163. ?acb    =       0           ;;number of arguments to a call
  164. ???     =       0           ;;byte count of local storage
  165. ?po     =       0           ;;byte count of parameters
  166. ?pas    =       0           ;;autosave value for procedure
  167. ?pc     =       0           ;;class of a procedure (near/far)
  168. ?ia     =       0           ;;no adjustment
  169. ?pu     =       0           ;;public flag for some macros
  170. ?adj    =       0           ;;initial define for .xcref
  171. ?rp     =       0           ;;count of register parameters
  172. ?uf     =       0           ;;user's frame code specified
  173. ?nd        =        0            ;;NODATA keyword specified
  174. ?nx        =        0            ;;ATOMIC keyword specified
  175. ?wfp    =       0           ;;window far procedure
  176. ?ff     =       0           ;;forceframe keyword specified
  177. ?dd2    =        0            ;;used for globalx and staticx
  178. ?cCall1 =        0            ;;used for cCalls
  179. ?pcc    =        ?PLM        ;;procedure calling convention
  180. ?PLMPrevParm =    0            ;;Used in parameter processing
  181. .xcref ?casen
  182. if1
  183. ?casen = 0
  184. endif
  185. ?n = 0000000000000000b
  186. ?ax = 0000000000000011b
  187. ?ah = 0000000000000001b
  188. ?al = 0000000000000010b
  189. ?bx = 0000000000001100b
  190. ?bh = 0000000000000100b
  191. ?bl = 0000000000001000b
  192. ?cx = 0000000000110000b
  193. ?ch = 0000000000010000b
  194. ?cl = 0000000000100000b
  195. ?dx = 0000000011000000b
  196. ?dh = 0000000001000000b
  197. ?dl = 0000000010000000b
  198. ?si = 0000000100000000b
  199. ?di = 0000001000000000b
  200. ?es = 0000010000000000b
  201. ?ds = 0000100000000000b
  202. ?bp = 0001000000000000b
  203. ?sp = 0010000000000000b
  204. ?ss = 0100000000000000b
  205. ?cs = 1000000000000000b
  206. .cref
  207.  
  208. ;;      uconcat - unconditionally generate a statement from a field
  209. ;;      of given parameters
  210. ;;
  211. ;;      usage:
  212. ;;        uconcat  a,b,c,d,e,f,g
  213. ;;
  214. ;;      where:
  215. ;;              a,b   are concatenated for field 1
  216. ;;              c,d   are concatenated for field 2
  217. ;;        e,f,g are concatenated for field 3
  218.  
  219. uconcat macro a,b,c,d,e,f,g
  220. a&b c&d e&f&g
  221. endm
  222.  
  223. ;;      mpush pushes multiple registers onto the stack according to
  224. ;;      a register specification.
  225. ;;
  226. ;;      format:
  227. ;;              mpush   r
  228. ;;
  229. ;;      where:
  230. ;;              r       is a numeric expression returned from ?ri
  231. ;;                      or any other valid register expression
  232.  
  233. mpush macro r
  234. irp x,<ax,bx,cx,dx,si,di,es,ds,bp,sp,ss,cs>
  235. %if (r and ??CM_Paste(?,x))
  236. push    x
  237. endif
  238. endm
  239. endm
  240.  
  241. ;;      mpop pops multiple registers from the stack according to
  242. ;;      a register specification.
  243. ;;
  244. ;;      format:
  245. ;;              mpop    r
  246. ;;
  247. ;;      where:
  248. ;;              r       is a numeric expression returned from ?ri
  249. ;;                      or any other valid register expression
  250.  
  251. mpop macro r
  252. irp x,<cs,ss,sp,bp,ds,es,di,si,dx,cx,bx,ax>
  253. %if (r and ??CM_Paste(?,x))
  254. pop    x
  255. endif
  256. endm
  257. endm
  258.  
  259. ;;      save - flag that the indicated registers are to be saved/restored
  260. ;;
  261. ;;    A flag is created which indicates which registers are to be saved
  262. ;;    when the cCall macro is invoked, and then restored after the call.
  263. ;;
  264. ;;      usage:
  265. ;;              save    <r>
  266. ;;
  267. ;;      where  r  is the list of registers to save, which may be:
  268. ;;
  269. ;;        register     saves
  270. ;;           AX          AX
  271. ;;           AH          AX
  272. ;;           AL          AX
  273. ;;           BX          BX
  274. ;;           BH          BX
  275. ;;           BL          BX
  276. ;;           CX          CX
  277. ;;           CH          CX
  278. ;;           CL          CX
  279. ;;           DX          DX
  280. ;;           DH          DX
  281. ;;           DL          DX
  282. ;;           SI          SI
  283. ;;           DI          DI
  284. ;;           ES          ES
  285. ;;           DS          DS
  286. ;;           BP          BP
  287. ;;
  288. ;;          none        nothing
  289. ;;
  290. ;;      the macro generates a value for the variable ?rsl
  291.  
  292. save macro r
  293. ?rsl=0
  294. ?ri ?rsl,<r>
  295. endm
  296.  
  297. ;;      ?ri - or register indexes to variable
  298. ;;
  299. ;;      ?ri is a macro that examines the passed argument list and computes
  300. ;;      a register index variable.
  301. ;;
  302. ;;    The values ORed with the variable are:
  303. ;;
  304. ;;              ?n       equ     0000000000000000b;
  305. ;;        ?AX     equ     0000000000000011b;
  306. ;;        ?AH     equ     0000000000000001b;
  307. ;;        ?AL     equ     0000000000000010b;
  308. ;;        ?BX     equ     0000000000001100b;
  309. ;;        ?BH     equ     0000000000000100b;
  310. ;;        ?BL     equ     0000000000001000b;
  311. ;;        ?CX     equ     0000000000110000b;
  312. ;;        ?CH     equ     0000000000010000b;
  313. ;;        ?CL     equ     0000000000100000b;
  314. ;;        ?DX     equ     0000000011000000b;
  315. ;;        ?DH     equ     0000000001000000b;
  316. ;;        ?DL     equ     0000000010000000b;
  317. ;;        ?SI     equ     0000000100000000b;
  318. ;;        ?DI     equ     0000001000000000b;
  319. ;;        ?ES     equ     0000010000000000b;
  320. ;;        ?DS     equ     0000100000000000b;
  321. ;;        ?BP     equ     0001000000000000b;
  322. ;;        ?SP     equ     0010000000000000b;
  323. ;;        ?SS     equ     0100000000000000b;
  324. ;;        ?CS     equ     1000000000000000b;
  325. ;;      usage:
  326. ;;              ?ri n,<r>
  327. ;;      where:
  328. ;;              n       is the variable to contain the new index value
  329. ;;              r       is the register list
  330.  
  331. ?ri macro n,r
  332. irp x,<r>
  333. %ifdef ??CM_Paste(?,x)
  334. %n=n or ??CM_Paste(?,x)
  335. endif
  336. endm
  337. endm
  338.  
  339. ;;      parmx - generate reference to parameter(s) on the stack
  340. ;;
  341. ;;    An equate is generated for addressing a paramter(s)
  342. ;;      on the stack for the current procedural frame.
  343. ;;
  344. ;;    An error message is generated if there isn't a current frame.
  345. ;;
  346. ;;      usage:
  347. ;;              parmx   n
  348. ;;      where:
  349. ;;              x       is the type of the argument(s)  b=byte, w=word, d=dword
  350. ;;              n       is the name(s) to be given the parameter(s).
  351. ;;
  352. ;;    Bytes are considered to be two bytes long for alignment.
  353. ;;
  354. ;;    The parmd form of the macro generates three equates:
  355. ;;
  356. ;;              name       -    for accessing the parameter as a double word
  357. ;;              off_name   -    for accessing the offset  (lsw) of the parameter
  358. ;;              seg_name   -    for accessing the segment (msw) of the parameter
  359.  
  360. .xcref
  361. .xcref parmB,parmW,parmD,parmQ,parmT,parmCP,parmDP,parmH
  362. .cref
  363. parmB macro n
  364. ?pp <n>,<byte>,2,1
  365. endm
  366. parmW macro n
  367. ?pp <n>,<word>,2,2
  368. endm
  369. parmD macro n
  370. ife ?pcc
  371. irp x,<n>
  372. ?pp <&&x>,<dword>,0,4
  373. ?pp <off_&&x>,<word>,2,2
  374. ?pp <seg_&&x>,<word>,2,2
  375. endm
  376. else
  377. irp x,<n>
  378. ?pp <seg_&&x>,<word>,2,2
  379. ?pp <off_&&x>,<word>,2,2
  380. ?pp <&&x>,<dword>,0,4
  381. endm
  382. endif
  383. endm
  384. parmH macro n
  385. ?pp <n>,<word>,4,2
  386. endm
  387. parmQ macro n
  388. ?pp <n>,<qword>,8,8
  389. endm
  390. parmT macro n
  391. ?pp <n>,<tbyte>,10,10
  392. endm
  393. if sizec
  394. parmCP macro n
  395. parmD <n>
  396. endm
  397. else
  398. parmCP macro n
  399. parmW <n>
  400. endm
  401. endif
  402. if sized
  403. parmDP macro n
  404. parmD <n>
  405. endm
  406. else
  407. parmDP macro n
  408. parmW <n>
  409. endm
  410. endif
  411.  
  412. ;;      ?pp is the generalized parameter definition macro
  413. ;;
  414. ;;      usage:
  415. ;;              ?pp m,t,l,s
  416. ;;
  417. ;;      where:
  418. ;;              n       is the name(s) of the parameters
  419. ;;              t       is the type (word, dword)
  420. ;;              l       is the length to update parameter byte count by
  421. ;;              s       is the internal typing size
  422.  
  423. ?pp macro n,t,l,s
  424. if ?cpd
  425. .xcref
  426. irp x,<n>
  427. %.xcref ??CM_Paste(?t_,x)
  428. %??CM_Paste(?t_,x)=s
  429. ife ?pcc
  430. ?pp1 x,<t>,,,%(?po+?adj)
  431. ?po=?po+l
  432. else
  433. ?PLMPrevParm=?PLMPrevParm+1
  434. ?po=?po+l
  435. ?pp1 x,<t>,%?po,%?adj,,%?PLMPrevParm,%(?PLMPrevParm-1)
  436. endif
  437. endm
  438. .cref
  439. else
  440. ??error <parm(s) "&n" declared outside proc def>
  441. endif
  442. endm
  443.  
  444. ;;    ?pp1 is the macro that generates the text equate for the
  445. ;;    parameter.  Two options exist, one for the C calling
  446. ;;      convention where the last parameter was the first pushed onto
  447. ;;    the stack ('C' convention), and one for the PL/M calling
  448. ;;      convention where the first parameter was the first
  449. ;;      pushed (also the same as ms-pascal).
  450. ;;
  451. ;;    The text generated will be of one of two forms:
  452. ;;
  453. ;;        name equ (type ptr [bp+(adj+offset)]) for C
  454. ;;           or
  455. ;;        name equ (type ptr [bp+adj+?po-offset]) for PL/M
  456. ;;
  457. ;;
  458. ;;    For C, since parameters are pushed first last, the offset
  459. ;;      plus the adjust will point to the correct parameter.
  460. ;;
  461. ;;    For PL/M, since parameters are pushed first first, the offset
  462. ;;    of a parameter is much more complicated.  A known portion of
  463. ;;      the offset can be computed when the text equate is generated.
  464. ;;
  465. ;;    What is known is the number of garbage bytes between BP and
  466. ;;      the nearest parameter (in this case the last parameter), and
  467. ;;      also how many bytes of parameters have preceeded this parameter.
  468. ;;
  469. ;;    What is unknown is how many total bytes of parameters there will
  470. ;;      be, which affects all the generated text equates since the offset
  471. ;;      from bp must be determined at some point.
  472. ;;
  473. ;;    Well, the offset from BP can be computed with one variable if
  474. ;;      the following is remembered:
  475. ;;
  476. ;;          the offset of any parameter from the first parameter is always
  477. ;;          the current parameter offset (?po).
  478. ;;
  479. ;;    With this in mind, you just have to figure out where the first
  480. ;;      parameter is, which is:
  481. ;;
  482. ;;              bp + garbage adjustment + distance to first parameter
  483. ;;         or
  484. ;;              bp + ?adj + ?po
  485. ;;
  486. ;;    This implies that any parameter can be defined as:
  487. ;;
  488. ;;              bp + ?adj + ?po -%?po
  489. ;;
  490. ;;    Make any sense?
  491. ;;
  492. ;;    For PL/M, a chain of self-purging macros will be generated
  493. ;;    which will pass the evaluated ?po to any previous incarnation
  494. ;;    of the macro.  This will allow the text equate to be generated
  495. ;;    with the actual offset instead of the symbolic ?po.
  496. ;;
  497. ;;
  498. ;;      usage:
  499. ;;        ?pp1    n,t,o,a,b,cpc,ppc
  500. ;;
  501. ;;      where:
  502. ;;              n    is the name to be given the equate
  503. ;;              t    is the type (byte, word, dword)
  504. ;;              o    is the offset from the first parameter
  505. ;;              a    is the adjustment
  506. ;;              b    is the adjustment plus the offset from the first parameter
  507. ;;        cpc  is the number of parameters so far
  508. ;;        ppc  is cpc - 1
  509.  
  510. ?pp1 macro n,t,o,a,b,cpc,ppc
  511. ife ?pcc
  512. n equ (t ptr [bp][+b])
  513. else
  514. .xcref
  515. .xcref ?PLMParm&cpc
  516. .cref
  517. ?PLMParm&cpc macro po
  518. uconcat <n>,,<equ>,,<(t ptr [bp][+>,%(a+po-o),<])>
  519. ?PLMParm&ppc po
  520. purge ?PLMParm&cpc
  521. endm
  522. endif
  523. endm
  524.  
  525. ;;    parmR - register parameter
  526. ;;
  527. ;;    parmR is the macro used for generating register parameters.
  528. ;;    The space allocated for the register parameters will be
  529. ;;      the ?ia (interface adjust) area which is between the  old
  530. ;;    BP and the first parameter.  Normally this is empty (?ia=0),
  531. ;;      or has the saved ds for a windows far procedure.
  532. ;;
  533. ;;    Byte and dword register parameters will be allowed.
  534. ;;
  535. ;;      usage:
  536. ;;        parmR    n,r,r2
  537. ;;      where:
  538. ;;              n       is the name of the parameter
  539. ;;              r       is the register it is in
  540. ;;              r2      is the offset register if a dword
  541.  
  542. ifndef ?NOPARMR
  543. .xcref
  544. .xcref ?pr,parmR
  545. .cref
  546. parmR macro n,r,r2
  547. ?pr n,r,r2,%?rp,%(?ia+2)
  548. endm
  549.  
  550.   ;;    ?pr - register parameter
  551.   ;;
  552.   ;;    ?pr is the actual macro for generating the equates for
  553.   ;;    register parameters.
  554.   ;;
  555.   ;;    usage:
  556.   ;;        parmR    n,r,r2,i,o
  557.   ;;    where:
  558.   ;;        n    is the name of the parameter
  559.   ;;        r    is the register it is in
  560.   ;;        r2    is the offset register if a dword
  561.   ;;        i    is the index of the ?rp to generate
  562.   ;;        o    is the offset from bp where the parm will be
  563.  
  564. ?pr macro n,r,r2,i,o
  565. .xcref
  566. ifnb <r2>
  567. parmR seg_&n,r
  568. parmR off_&n,r2
  569. n equ (dword ptr [bp][-o-2])
  570. .xcref ?t_&n
  571. ?t_&n=4
  572. else
  573. .xcref ?rp&i
  574. ?rp&i=0
  575. ifdef ?&r
  576. ?rp&i=?&r
  577. endif
  578. if ??? or (?cpd eq 0) or (?rp&i eq 0)
  579. ??error <invalid parmR encountered: &n,&r>
  580. exitm
  581. endif
  582. n equ (word ptr [bp][-o])
  583. .xcref ?t_&n
  584. ?t_&n=2
  585. irp x,<bh,ch,dh,bl,cl,dl,ah,al>
  586. %if ??CM_Paste(?,x) eq ??CM_Paste(?,r)
  587. n equ (byte ptr [bp][-o])
  588. %??CM_Paste(?t_,n)=1
  589. exitm
  590. endif
  591. endm
  592. ?ia=?ia+2
  593. ?rp=?rp+1
  594. endif
  595. .cref
  596. endm
  597. endif
  598.  
  599. ;;      localx - generate reference to a local variable on the stack
  600. ;;
  601. ;;    An equate is generated for addressing a local variable
  602. ;;      on the stack for the current procedural frame.
  603. ;;
  604. ;;      usage:
  605. ;;              localx    n
  606. ;;      where:
  607. ;;              x       is the type b=byte, w=word, d=dword, v=variable size
  608. ;;              n       is the name(s) to be given the variable(s).
  609. ;;
  610. ;;    Bytes are considered to be two bytes long for alignment reasons
  611. ;;
  612. ;;    The locald form of the macro generates three equates:
  613. ;;
  614. ;;              name       -    for accessing the variable as a double word
  615. ;;              off_name   -    for accessing the offset  (lsw) of the variable
  616. ;;              seg_name   -    for accessing the segment (msw) of the variable
  617.  
  618. .xcref
  619. .xcref localB,localW,localD,localQ,localT,localCP,localDP,localV
  620. .cref
  621. localB macro n
  622. ?aloc <n>,<byte ptr>,1,1,0
  623. endm
  624. localW macro n
  625. ?aloc <n>,<word ptr>,2,2,1
  626. endm
  627. localD macro n
  628. irp x,<n>
  629. ?aloc <seg_&&x>,<word ptr>,2,2,1
  630. ?aloc <off_&&x>,<word ptr>,2,2,1
  631. ?aloc <&&x>,<dword ptr>,0,4,1
  632. endm
  633. endm
  634. localQ macro n
  635. ?aloc <n>,<qword ptr>,8,8,1
  636. endm
  637. localT macro n
  638. ?aloc <n>,<tbyte ptr>,10,10,1
  639. endm
  640. if sizec
  641. localCP macro n
  642. localD <n>
  643. endm
  644. else
  645. localCP macro n
  646. localW <n>
  647. endm
  648. endif
  649. if sized
  650. localDP macro n
  651. localD <n>
  652. endm
  653. else
  654. localDP macro n
  655. localW <n>
  656. endm
  657. endif
  658. localV macro n,a
  659. ?aloc <n>,,%(a),0,1
  660. endm
  661.  
  662. ;;      ?aloc is the macro that actually allocates local storage.
  663. ;;      it is only invoked by the localx macros.
  664. ;;
  665. ;;      usage:
  666. ;;              ?aloc  n,t,l,s,a
  667. ;;      where:
  668. ;;              n      is a list of names of local variable of the
  669. ;;                      given type.
  670. ;;              t       is the text string for the given variable
  671. ;;                      and is one of:
  672. ;;                          word  ptr
  673. ;;                          dword ptr
  674. ;;                          byte  ptr
  675. ;;                      or alternatively left blank for variable size
  676. ;;                      allocations (no implicit type).
  677. ;;              l       is the size of the variable in bytes
  678. ;;              s       is the internal type flag (size), and is one of:
  679. ;;                              word     - 2
  680. ;;                              dword    - 4
  681. ;;                              byte     - 1
  682. ;;                              variable - 0
  683. ;;              a       is a flag indicating that word alignment is to be
  684. ;;                      forced for this type of item.
  685. ;;
  686. ;;    NOTE:    It is assumed that the stack is already aligned on a word
  687. ;;        boundary when the cProc is invoked.  The macros will guarantee
  688. ;;        to allocate an even number of bytes on the stack to maintain
  689. ;;              word alignment.
  690.  
  691. ?aloc macro n,t,l,s,a
  692. if ?cpd
  693. .xcref
  694. irp x,<n>
  695. ???=???+l
  696. if a
  697. ???=((??? + 1) and 0fffeh)
  698. endif
  699. ?al1 x,<t>,%(???+?ia)
  700. %.xcref ??CM_Paste(?t_,x)
  701. %??CM_Paste(?t_,x)=s
  702. endm
  703. .cref
  704. else
  705. ??error <locals "&n" declared outside procedure def>
  706. endif
  707. endm
  708.  
  709. ;;      ?al1 - allocate local, continued.
  710. ;;
  711. ;;      ?al1 actually generates the text equate for the local variable.
  712. ;;    The form of the text equate generated is more or less:
  713. ;;
  714. ;;        name equ (type ptr [bp-?ia-nn])
  715. ;;          or
  716. ;;        name equ ([bp-?ia-nn])
  717. ;;
  718. ;;      where:
  719. ;;              ?ia   is defined to be either zero, or is defined to be
  720. ;;              the number of bytes between the saved BP and the first
  721. ;;              local.  ?ia is only applicable if the current cProc is
  722. ;;              a windows far procedure or if parmRs have been
  723. ;;              encountered.  If not, the ?ia will be zero.  since ?ia
  724. ;;              is determinable prior to invoking this macro, it will be
  725. ;;              added into the  offset ("nn") passed to this macro
  726. ;;
  727. ;;      usage:
  728. ;;              ?al1 n,t,o
  729. ;;      where:
  730. ;;              n    is the name for the text equate
  731. ;;              t    is the type of the equate
  732. ;;              o    is the offset of the equate
  733.  
  734. ?al1 macro n,t,o
  735. n equ (t [bp][-o])
  736. endm
  737.  
  738. ;;    ?gcc - get calling convention
  739. ;;
  740. ;;    ?gcv sets the given symbol to the calling convention
  741. ;;    to be used.
  742. ;;
  743. ;;    usage:
  744. ;;        ?gcc s,i,cc
  745. ;;
  746. ;;    where:
  747. ;;        s  is the symbol to return the convention in
  748. ;;           s = 0 if 'C' calling convention
  749. ;;           s = 1 if PL/M (PASCAL) calling convention
  750. ;;        i  is the initial value for s
  751. ;;        cc is the calling convention override, and may be one of
  752. ;;           C      use 'C' convention
  753. ;;           PLM      use PL/M calling convention
  754. ;;           PASCAL use PL/M calling convention
  755.  
  756. ?gcc macro s,i,cc
  757. s = i
  758. ifnb <cc>
  759. ifidn <cc>,<C>
  760. s=0
  761. endif
  762. ifidn <cc>,<PLM>
  763. s=1
  764. endif
  765. ifidn <cc>,<PASCAL>
  766. s=1
  767. endif
  768. endif
  769. endm
  770. ifndef ?NOGLOBAL
  771. .xcref
  772. .xcref globalB,globalW,globalD,globalQ,globalT,globalCP,globalDP
  773.  
  774.   ;;    globalx - define global data of type x
  775.   ;;
  776.   ;;    usage:
  777.   ;;        globalx n,i,s,c
  778.   ;;    where:
  779.   ;;        x    is the type of the variable  b=byte, w=word, d=dword
  780.   ;;            q=quad word, t=tenbytes, cp=code pointer, dp=data pointer
  781.   ;;        n    is the name to be given the variable.
  782.   ;;        i    is the initial value of the variable.
  783.   ;;        s    is the duplication factor
  784.   ;;        c    is the convention, C for C, PLM or PASCAL for PL/M.
  785.   ;;            The default (?PLM flag) will be used if not specified.
  786.   ;;
  787.   ;;    The D form will generate two extra equates of the form off_n and seg_n.
  788.  
  789. .cref
  790. globalB macro n,i,s,c
  791. ?ad <n>,1
  792. ?dd n,1,<byte>,<db>,<i>,<s>,<c>
  793. endm
  794. globalW macro n,i,s,c
  795. ?ad <n>,2
  796. ?dd n,1,<word>,<dw>,<i>,<s>,<c>
  797. endm
  798. globalD macro n,i,s,c
  799. ?ad <n>,4
  800. ?dd n,1,<dword>,<dd>,<i>,<s>,<c>
  801. off_&n equ word ptr n[0]
  802. seg_&n equ word ptr n[2]
  803. endm
  804. globalQ macro n,i,s,c
  805. ?ad <n>,8
  806. ?dd n,1,<qword>,<dq>,<i>,<s>,<c>
  807. endm
  808. globalT macro n,i,s,c
  809. ?ad <n>,10
  810. ?dd n,1,<tbyte>,<dt>,<i>,<s>,<c>
  811. endm
  812. if sizec
  813. globalCP macro n,i,s,c
  814. globalD n,<i>,<s>,<c>
  815. endm
  816. else
  817. globalCP macro n,i,s,c
  818. globalW n,<i>,<s>,<c>
  819. endm
  820. endif
  821. if sized
  822. globalDP macro n,i,s,c
  823. globalD n,<i>,<s>,<c>
  824. endm
  825. else
  826. globalDP macro n,i,s,c
  827. globalW n,<i>,<s>,<c>
  828. endm
  829. endif
  830. endif
  831. ifndef ?NOSTATIC
  832. .xcref
  833. .xcref staticB,staticW,staticD,staticQ,staticT,staticCP,staticDP
  834.  
  835.   ;;    staticx - define static data of type x
  836.   ;;
  837.   ;;    usage:
  838.   ;;        staticx n,i,s
  839.   ;;    where:
  840.   ;;        x    is the type of the variable  b=byte, w=word, d=dword
  841.   ;;            q=quad word, t=tenbytes, cp=code pointer, dp=data pointer
  842.   ;;        n    is the name to be given the variable.
  843.   ;;        i    is the initial value of the variable.
  844.   ;;        s    is the duplication factor
  845.   ;;
  846.   ;;    statics do not generate an underscored version of the symbol
  847.   ;;    since they are intended to be internal symbols.  If they are
  848.   ;;    required to be public, use globlax.
  849.  
  850. .cref
  851. staticB macro n,i,s
  852. ?ad <n>,1
  853. ?dd n,0,<byte>,<db>,<i>,<s>,<PLM>
  854. endm
  855. staticW macro n,i,s
  856. ?ad <n>,2
  857. ?dd n,0,<word>,<dw>,<i>,<s>,<PLM>
  858. endm
  859. staticD macro n,i,s
  860. ?ad <n>,4
  861. ?dd n,0,<dword>,<dd>,<i>,<s>,<PLM>
  862. endm
  863. staticQ macro n,i,s
  864. ?ad <n>,8
  865. ?dd n,0,<qword>,<dq>,<i>,<s>,<PLM>
  866. endm
  867. staticT macro n,i,s
  868. ?ad <n>,10
  869. ?dd n,0,<tbyte>,<dt>,<i>,<s>,<PLM>
  870. endm
  871. if sizec
  872. staticCP macro n,i,s
  873. staticD n,<i>,<s>
  874. endm
  875. else
  876. staticCP macro n,i,s
  877. staticW n,<i>,<s>
  878. endm
  879. endif
  880. if sized
  881. staticDP macro n,i,s
  882. staticD n,<i>,<s>
  883. endm
  884. else
  885. staticDP macro n,i,s
  886. staticW n,<i>,<s>
  887. endm
  888. endif
  889. endif
  890.  
  891.   ;;    staticx - define static data of type x
  892.   ;;
  893.   ;;    usage:
  894.   ;;        staticx n,i,s
  895.   ;;    where:
  896.   ;;        x    is the type of the variable  b=byte, w=word, d=dword
  897.   ;;            q=quad word, t=tenbytes, cp=code pointer, dp=data pointer
  898.   ;;        n    is the name to be given the variable.
  899.   ;;        i    is the initial value of the variable.
  900.   ;;        s    is the duplication factor
  901.   ;;
  902.   ;;    statics do not generate an underscored version of the symbol
  903.   ;;    since they are intended to be internal symbols.  If they are
  904.   ;;    required to be public, use globlax.
  905.  
  906. ?dd macro n,p,t,d,i,s,c
  907. ?gcc ?dd2,%?PLM,<c>
  908. ife ?dd2
  909. n label t
  910. ?dd1 _&n,p,<d>,<i>,<s>
  911. else
  912. ?dd1 n,p,<d>,<i>,<s>
  913. endif
  914. endm
  915.  
  916. ;;      ?dd1 is the generalized data definition macro.
  917. ;;
  918. ;;      format:
  919. ;;              ?dd1 n,p,d,i,s
  920. ;;      where:
  921. ;;              n       is the name of the procedure
  922. ;;              p       is the public flag
  923. ;;              d       is the assembler directive (db,dw or dd)
  924. ;;              i       is the initial value
  925. ;;              s       is a duplication factor
  926.  
  927. ?dd1 macro n,p,d,i,s
  928. if p
  929. public n
  930. endif
  931. ifb <s>
  932. n d i
  933. else
  934. ifb <i>
  935. n d s dup (?)
  936. else
  937. n d s dup (i)
  938. endif
  939. endif
  940. endm
  941. ifndef ?NOEXTERN
  942. .xcref
  943. .xcref ?ex1,?ex2,externB,externW,externD,externQ,externT
  944. .xcref externNP,externFP,externP,externCP,externDP,externA
  945. .cref
  946. ?ex2 = 0
  947.  
  948.   ;;    externx - define external data of type x
  949.   ;;
  950.   ;;    usage:
  951.   ;;        externx n,c
  952.   ;;    where:
  953.   ;;        x    is the type of the variable  b=byte, w=word, d=dword
  954.   ;;            q=quad word, t=tenbytes, cp=code pointer
  955.   ;;            dp=data pointer,  a=absolute
  956.   ;;        n    is a list of names to define
  957.   ;;        c    is the convention, C for C, PLM or PSACAL forPL/M.
  958.   ;;            The default (?PLM flag) will be used if not specified.
  959.  
  960. externA macro n,c
  961. ?ex1 <n>,40h,<abs>,<c>,<>
  962. endm
  963. externB macro n,c
  964. ?ex1 <n>,1,<byte>,<c>,<>
  965. endm
  966. externW macro n,c
  967. ?ex1 <n>,2,<word>,<c>,<>
  968. endm
  969. externD macro n,c
  970. ?ex1 <n>,4,<dword>,<c>,<>
  971. endm
  972. externQ macro n,c
  973. ?ex1 <n>,8,<qword>,<c>,<>
  974. endm
  975. externT macro n,c
  976. ?ex1 <n>,10,<tbyte>,<c>,<>
  977. endm
  978. externNP macro n,c
  979. ?ex1 <n>,2,<near>,<c>,<cc>
  980. endm
  981. externFP macro n,c
  982. ?ex1 <n>,4,<far>,<c>,<cc>
  983. endm
  984. if sizec
  985. externP macro n,c
  986. ?ex1 <n>,4,<far>,<c>,<cc>
  987. endm
  988. else
  989. externP macro n,c
  990. ?ex1 <n>,2,<near>,<c>,<cc>
  991. endm
  992. endif
  993. if sizec
  994. externCP macro n,c
  995. ?ex1 <n>,4,<dword>,<c>,<>
  996. endm
  997. else
  998. externCP macro n,c
  999. ?ex1 <n>,2,<word>,<c>,<>
  1000. endm
  1001. endif
  1002. if sized
  1003. externDP macro n,c
  1004. ?ex1 <n>,4,<dword>,<c>,<>
  1005. endm
  1006. else
  1007. externDP macro n,c
  1008. ?ex1 <n>,2,<word>,<c>,<>
  1009. endm
  1010. endif
  1011.  
  1012.   ;;    ?ex1 is the generalized external definition macro
  1013.   ;;
  1014.   ;;    format:
  1015.   ;;        ?ex1 n,s,d,c,scv
  1016.   ;;    where:
  1017.   ;;        n    is are the names of the externals
  1018.   ;;        s    is the size in bytes (used for typing)
  1019.   ;;        d    is the type
  1020.   ;;        c    is the convention, C for C, PLM or PSACAL for PL/M.
  1021.   ;;            The default (?PLM flag) will be used if not specified.
  1022.   ;;        scv    save calling convention.  If this field is "cc", then
  1023.   ;;            the calling convention will be saved in a ?CCn equ.
  1024.  
  1025. ?ex1 macro n,s,d,c,scv
  1026. ?gcc ?ex2,%?PLM,<c>
  1027. irp x,<n>
  1028. .xcref
  1029. %.xcref ??CM_Paste(?t_,x)
  1030. .cref
  1031. %??CM_Paste(?t_,x)=s
  1032. ife ?ex2
  1033. %extrn ??CM_Paste(_,x):&d
  1034. %x equ ??CM_Paste(_,x)
  1035. else
  1036. extrn x:&d
  1037. endif
  1038. ifidn <scv>,<cc>
  1039. .xcref
  1040. %.xcref ??CM_Paste(?CC,x)
  1041. .cref
  1042. %??CM_Paste(?CC,x)=?ex2
  1043. endif
  1044. endm
  1045. endm
  1046. endif
  1047. ifndef ?NOLABEL
  1048. .xcref
  1049. .xcref ?lb1,?lblpu,?lb2
  1050. .xcref labelB,labelW,labelD,labelQ,labelT
  1051. .xcref labelNP,labelFP,labelP,labelCP,labelDP
  1052. .cref
  1053. ?lblpu = 0
  1054. ?lb2 = 0
  1055.  
  1056.   ;;      labelx - define label of data type x
  1057.   ;;
  1058.   ;;      usage:
  1059.   ;;          labelx n,c
  1060.   ;;      where:
  1061.   ;;        x    is the type of the variable  b=byte, w=word, d=dword
  1062.   ;;            q=quad word, t=tenbytes, cp=code pointer, dp=data pointer
  1063.   ;;        n    is a list of names to define, the first of which can
  1064.   ;;            be the keyword public
  1065.   ;;        c    is the convention, C for C, PLM or PSACAL for PL/M.
  1066.   ;;            The default (?PLM flag) will be used if not specified.
  1067.  
  1068. labelB macro n,c
  1069. ?lb1 <n>,1,<byte>,<c>
  1070. endm
  1071. labelW macro n,c
  1072. ?lb1 <n>,2,<word>,<c>
  1073. endm
  1074. labelD macro n,c
  1075. ?lb1 <n>,4,<dword>,<c>
  1076. endm
  1077. labelQ macro n,c
  1078. ?lb1 <n>,8,<qword>,<c>
  1079. endm
  1080. labelT macro n,c
  1081. ?lb1 <n>,10,<tbyte>,<c>
  1082. endm
  1083. labelNP macro n,c
  1084. ?lb1 <n>,2,<near>,<c>
  1085. endm
  1086. labelFP macro n,c
  1087. ?lb1 <n>,4,<far>,<c>
  1088. endm
  1089. if sizec
  1090. labelP macro n,c
  1091. ?lb1 <n>,4,<far>,<c>
  1092. endm
  1093. else
  1094. labelP macro n,c
  1095. ?lb1 <n>,2,<near>,<c>
  1096. endm
  1097. endif
  1098. if sizec
  1099. labelCP macro n,c
  1100. ?lb1 <n>,4,<dword>,<c>
  1101. endm
  1102. else
  1103. labelCP macro n,c
  1104. ?lb1 <n>,2,<word>,<c>
  1105. endm
  1106. endif
  1107. if sized
  1108. labelDP macro n,c
  1109. ?lb1 <n>,4,<dword>,<c>
  1110. endm
  1111. else
  1112. labelDP macro n,c
  1113. ?lb1 <n>,2,<word>,<c>
  1114. endm
  1115. endif
  1116.  
  1117.   ;;    ?lb1 is the generalized label definition macro
  1118.   ;;
  1119.   ;;    format:
  1120.   ;;        ?lb1 n,s,d
  1121.   ;;    where:
  1122.   ;;        n    are the names of the labels
  1123.   ;;        s    is the size in bytes (used for typing)
  1124.   ;;        d    is the type
  1125.   ;;        c    is the convention, C for C, PLM or PSACAL for PL/M.
  1126.   ;;            The default (?PLM flag) will be used if not specified.
  1127.  
  1128. ?lb1 macro n,s,d,c
  1129. ?gcc ?lb2,%?PLM,<c>
  1130. ?lblpu=0
  1131. irp x,<n>
  1132. ifidn <x>,<PUBLIC>
  1133. ?lblpu=1
  1134. else
  1135. .xcref
  1136. %.xcref ??CM_Paste(?t_,x)
  1137. .cref
  1138. %??CM_Paste(?t_,x)=s
  1139. ife ?lb2
  1140. if ?lblpu
  1141. %public ??CM_Paste(_,x)
  1142. endif
  1143. %??CM_Paste(_,x) label &d
  1144. %x equ ??CM_Paste(_,x)
  1145. else
  1146. if ?lblpu
  1147. public x
  1148. endif
  1149. x label &d
  1150. endif
  1151. endif
  1152. endm
  1153. endm
  1154. endif
  1155. ifndef ?NODEF
  1156. .xcref
  1157. .xcref defB,defW,defD,defQ,defT,defCP,defDP
  1158. .cref
  1159.  
  1160.   ;;    defx - inform macros that name is of type x
  1161.   ;;
  1162.   ;;    The given name(s) is flaged to be of the given type.  This macro
  1163.   ;;    is intended for giving types to variables that were not generated
  1164.   ;;    by the macros (i.e., static storage).  There must be a type definition
  1165.   ;;    for all parameters in a call list.
  1166.   ;;
  1167.   ;;    usage:
  1168.   ;;        defx    n
  1169.   ;;    where:
  1170.   ;;        x    is the type of the variable  b=byte, w=word, d=dword
  1171.   ;;        n      is the name(s) to be given the variable(s).
  1172.   ;;
  1173.   ;;    Bytes are considered to be two bytes long for alignment reasons
  1174.  
  1175. defB macro n
  1176. ?ad <n>,1
  1177. endm
  1178. defW macro n
  1179. ?ad <n>,2
  1180. endm
  1181. defD macro n
  1182. ?ad <n>,4
  1183. endm
  1184. defQ macro n
  1185. ?ad <n>,8
  1186. endm
  1187. defT macro n
  1188. ?ad <n>,10
  1189. endm
  1190. if sizec
  1191. defCP macro n
  1192. defD <n>
  1193. endm
  1194. else
  1195. defCP macro n
  1196. defW <n>
  1197. endm
  1198. endif
  1199. if sized
  1200. defDP macro n
  1201. defD <n>
  1202. endm
  1203. else
  1204. defDP macro n
  1205. defW <n>
  1206. endm
  1207. endif
  1208. endif
  1209.  
  1210. ;    ?ad is the macro which creates a definition for the given
  1211. ;    symbol
  1212. ;
  1213. ;    usage:
  1214. ;        ?ad <n>,s
  1215. ;    where:
  1216. ;        n is a list of names to define
  1217. ;        s is the size info (1,2,4,8,10)
  1218.  
  1219. ?ad macro n,s
  1220. irp x,<n>
  1221. .xcref
  1222. %.xcref ??CM_Paste(?t_,x)
  1223. .cref
  1224. %??CM_Paste(?t_,x)=s
  1225. endm
  1226. endm
  1227. ifndef ?NOPTR
  1228. .xcref
  1229. .xcref regPtr,farPtr
  1230. .cref
  1231.  
  1232.   ;;    regPtr generates information allowing a 32-bit pointer currently
  1233.   ;;    in a register to be pushed as a parameter to a subroutine using
  1234.   ;;    the cCall macro.
  1235.   ;;
  1236.   ;;    usage:
  1237.   ;;        regptr    n,s,o
  1238.   ;;    where:
  1239.   ;;        n    is the name the argument will be known as
  1240.   ;;        s    is the register containing the segment portion
  1241.   ;;            of the pointer
  1242.   ;;        o    is the register containing the offset portion
  1243.   ;;            of the pointer
  1244.   ;;
  1245.   ;;    2/14/85 - made obsolete with farptr
  1246.  
  1247. regPtr macro n,s,o
  1248. farPtr n,s,o
  1249. endm
  1250.  
  1251.   ;;    farPtr generates information allowing a 32-bit pointer to be
  1252.   ;;    pushed as a parameter to a subroutine using the cCall macro.
  1253.   ;;
  1254.   ;;    usage:
  1255.   ;;        farptr    n,s,o
  1256.   ;;    where:
  1257.   ;;        n    is the name the argument will be known as
  1258.   ;;        s    is the segment portion of the pointer
  1259.   ;;        o    is the offset portion of the pointer
  1260.   ;;
  1261.   ;;    Note that any cast must have been made in the argument itself
  1262.   ;;    (i.e. regptr ptr1,ds,<word ptr 3[si]>)
  1263.  
  1264. farPtr macro n,s,o
  1265. .xcref
  1266. .xcref ?t_&n
  1267. .cref
  1268. n macro
  1269.     push    s
  1270.     push    o
  1271. endm
  1272. ?t_&n=80h
  1273. endm
  1274. endif
  1275.  
  1276. ;;      arg - declare argument
  1277. ;;
  1278. ;;    The given argument(s) is added to the argument list structure
  1279. ;;
  1280. ;;      format:
  1281. ;;              arg     a
  1282. ;;
  1283. ;;      where:
  1284. ;;              a       is any valid argument to push.
  1285. ;;
  1286. ;;    If any element in arglist has not been defined or isn't a 16-bit
  1287. ;;      register, then a complete specification must have been given in a
  1288. ;;      text equate and a defx also given (if not, you'll pay the penalty!)
  1289.  
  1290. arg macro a
  1291. irp x,<a>
  1292. ?argc=?argc+1
  1293. ?atal <x>,%?argc
  1294. endm
  1295. endm
  1296.  
  1297. ;;      ?atal (add to argument list) generates a macro that will cause
  1298. ;;    the given argument to be processed when invoked.  It is used by
  1299. ;;      the arg macro only.
  1300.  
  1301. ?atal macro n,i
  1302. .xcref
  1303. .xcref ?ali&i
  1304. .cref
  1305. ?ali&i macro
  1306. ?ap <n>
  1307. endm
  1308. endm
  1309.  
  1310. ;;      ?ap - process arguments and place onto stack
  1311. ;;
  1312. ;;    The given argument is processed (type checking) and place on
  1313. ;;    the stack for a pending call.  There must be a type definition
  1314. ;;    for all arguments (except words).  This can be done by using
  1315. ;;      text equates and the defx macro.
  1316. ;;
  1317. ;;      format:
  1318. ;;              ?ap n
  1319. ;;      where:
  1320. ;;              n       is the name of the argument to be pushed
  1321. ;;
  1322. ;;    The variable  ?argl  is updated by the length of the arguments
  1323. ;;      pushed so that the stack can be cleaned up after the call.
  1324.  
  1325. ?ap macro n
  1326. ?argl=?argl+2
  1327. ifdef ?t_&n
  1328. ife ?t_&n-1
  1329.     push    word ptr (n)
  1330. exitm
  1331. endif
  1332. ife ?t_&n-2
  1333.     push    n
  1334. exitm
  1335. endif
  1336. ife ?t_&n-4
  1337.     push    word ptr (n)[2]
  1338.     push    word ptr (n)
  1339. ?argl=?argl+2
  1340. exitm
  1341. endif
  1342. ife ?t_&n-8
  1343.     push    word ptr (n)[6]
  1344.     push    word ptr (n)[4]
  1345.     push    word ptr (n)[2]
  1346.     push    word ptr (n)
  1347. ?argl=?argl+6
  1348. exitm
  1349. endif
  1350. if ?t_&n and 80h
  1351. n
  1352. ?argl=?argl+2
  1353. exitm
  1354. endif
  1355. ife ?t_&n
  1356.     push    word ptr (n)
  1357. exitm
  1358. endif
  1359. endif
  1360.     push    n
  1361. endm
  1362.  
  1363. ;;    cCall - call a 'c' language procedure
  1364. ;;
  1365. ;;    The given procedure is called with the given parameters.
  1366. ;;    If the calling convention is C, the arguments are pushed
  1367. ;;      in reverse order, and removed after the called procedure
  1368. ;;    returns.  If the calling conventing is PL/M, the arguments
  1369. ;;      are pushed as they were encountered, and the called procedure
  1370. ;;      is assumed to have removed them from the stack.
  1371. ;;
  1372. ;;    The calling convention priority will be:
  1373. ;;       1)    that specified on the cCall if present
  1374. ;;       2)    that defined by the target
  1375. ;;       3)    the default (?PLM flag)
  1376. ;;
  1377. ;;      format:
  1378. ;;        ccall n,<a>,c
  1379. ;;
  1380. ;;      where:
  1381. ;;              n       is the name of the procedure to call
  1382. ;;              a       are arguments to be pushed (optional, may be
  1383. ;;                      specified with the "arg" macro.
  1384. ;;        c    is the convention, C for C, PLM or PSACAL for PL/M.
  1385. ;;            The default (?PLM flag) will be used if not specified.
  1386.  
  1387. cCall macro n,a,c
  1388. ifnb <a>
  1389. arg <a>
  1390. endif
  1391. mpush %?rsl
  1392. ifdef ?CC&n
  1393. ?cCall1=?CC&n
  1394. else
  1395. ?cCall1=?PLM
  1396. endif
  1397. ifnb <c>
  1398. ?gcc ?cCall1,%?cCall1,<c>
  1399. endif
  1400. ?argl=0
  1401. ife ?cCall1
  1402. ?acb=?argc
  1403. else
  1404. ?acb=1
  1405. endif
  1406. rept ?argc
  1407. uconcat <?ali>,%?acb
  1408. uconcat <purge>,,<?ali>,%?acb
  1409. ife ?cCall1
  1410. ?acb=?acb-1
  1411. else
  1412. ?acb=?acb+1
  1413. endif
  1414. endm
  1415.     call    n
  1416. if ((?cCall1 eq 0) and (?argl ne 0))
  1417.     add    sp,?argl
  1418. endif
  1419. mpop %?rsl
  1420. ?rsl=0
  1421. ?argc= 0
  1422. ?argl= 0
  1423. endm
  1424.  
  1425. ;;    cProc - define a 'c' procedure
  1426. ;;
  1427. ;;    cProc is the procedure definition for procedures.
  1428. ;;
  1429. ;;      format:
  1430. ;;        cProc n,cf,a
  1431. ;;      where:
  1432. ;;              n       is the name of the procedure
  1433. ;;
  1434. ;;        cf    controls certain definitions, and may be:
  1435. ;;                NEAR       proc is to be a near label
  1436. ;;                FAR        proc is to be a far  label
  1437. ;;                PUBLIC     proc is to be defined as public
  1438. ;;                SMALL      call makeframe procedure
  1439. ;;                NODATA     dont create prolog code to setup DS
  1440. ;;                ATOMIC     don't link stack if not needed
  1441. ;;                       NODATA must be specified for ATOMIC
  1442. ;;                FORCEFRAME Force generation of a frame
  1443. ;;                C           proc is to be a C    procedure
  1444. ;;                PLM        proc is to be a PL/M procedure
  1445. ;;                PASCAL     proc is to be a PL/M procedure
  1446. ;;                WIN        proc is to be a windows procedure
  1447. ;;                NONWIN     proc isn't to be a windows procedure
  1448. ;;
  1449. ;;              a       is a list of registers that are to be saved whenever
  1450. ;;                      the procedure is invoked.
  1451. ;;
  1452. ;;            makeframe procedure:   If small is specified, then
  1453. ;;                      the "makeframe procedure" is invoked instead of
  1454. ;;                      generating normal prologues/epilogues
  1455. ;;
  1456. ;;            A call is performed to the makeframe procedure.  The
  1457. ;;                      call is followed by two bytes.  the first byte is the
  1458. ;;                      number of locals to allocate for the frame, the second
  1459. ;;            is the number of bytes of parameters.  The makeframe
  1460. ;;            procedure will in turn call the cProc routine at the
  1461. ;;            address following the data bytes.  When the cProc is
  1462. ;;                      finished, it will do a near return to the makeframe
  1463. ;;                      procedure to clean up the frame and exit.
  1464. ;;
  1465. ;;            Note that register parameters and makeframe are
  1466. ;;                      incompatible and cannot be used together.
  1467. ;;
  1468. ;;            The makeframe procedure will save SI, DI, and also
  1469. ;;            DS if a far procedure.    These registers will be
  1470. ;;                      removed from the autosave list if specified.
  1471.  
  1472. cProc macro n,cf,a
  1473. if ?cpd
  1474. ?utpe
  1475. endif
  1476. ?cpd=1
  1477. ???=0
  1478. ?argc=0
  1479. ?ba=0
  1480. ?po=0
  1481. ?pu=0
  1482. ?ia=0
  1483. ?adj=4
  1484. ?rp=0
  1485. ?uf=0
  1486. ?wfp=?WIN
  1487. ?ff=0
  1488. ?pas=0
  1489. ?pcc=?PLM
  1490. ifnb <a>
  1491. ?ri ?pas,<a>
  1492. endif
  1493. ?pc=sizec
  1494. ?nd=?nodata1
  1495. ?nx=0
  1496. irp x,<cf>
  1497. ifidn <x>,<FAR>
  1498. ?pc=1
  1499. endif
  1500. ifidn <x>,<NEAR>
  1501. ?pc=0
  1502. endif
  1503. ifidn <x>,<PUBLIC>
  1504. ?pu=1
  1505. endif
  1506. ifidn <x>,<SMALL>
  1507. ?uf=1
  1508. endif
  1509. ifidn <x>,<DATA>
  1510. ?nd=0
  1511. endif
  1512. ifidn <x>,<NODATA>
  1513. ?nd=1
  1514. endif
  1515. ifidn <x>,<ATOMIC>
  1516. ?nx=1
  1517. endif
  1518. ifidn <x>,<FORCEFRAME>
  1519. ?ff=1
  1520. endif
  1521. ifidn <x>,<C>
  1522. ?pcc=0
  1523. endif
  1524. ifidn <x>,<PLM>
  1525. ?pcc=1
  1526. endif
  1527. ifidn <x>,<PASCAL>
  1528. ?pcc=1
  1529. endif
  1530. ifidn <x>,<WIN>
  1531. ?wfp=1
  1532. endif
  1533. ifidn <x>,<NONWIN>
  1534. ?wfp=0
  1535. endif
  1536. endm
  1537. if ?pcc
  1538. ?PLMPrevParm=0
  1539. .xcref
  1540. .xcref ?PLMParm0
  1541. .cref
  1542. ?PLMParm0 macro arg
  1543. purge ?PLMParm0
  1544. endm
  1545. endif
  1546. .xcref
  1547. .xcref ?CC&n
  1548. .cref
  1549. ?CC&n=?pcc
  1550. if (?nx eq 1) and (?nd eq 0)
  1551. ?nx = 0
  1552. ??error <ATOMIC specified without NODATA - ATOMIC ignored>
  1553. endif
  1554. if ?pc
  1555. if ?wfp
  1556. ife ?nx
  1557. ?ia=2
  1558. ?pas = ?pas and (not ?ds)
  1559. endif
  1560. endif
  1561. ?adj=?adj+2
  1562. else
  1563. ?wfp=0
  1564. endif
  1565. ?pas = ?pas and (not (?sp+?cs+?ss))
  1566. if ?uf
  1567. ?pas = ?pas and (not (?bp+?si+?di))
  1568. endif
  1569. ife ?pcc
  1570. ?pg <_&n>,%?pu,%?pc,%?pas,%?wfp,<n>,%?pcc
  1571. else
  1572. ?pg <n>,%?pu,%?pc,%?pas,%?wfp,<n>,%?pcc
  1573. endif
  1574. endm
  1575.  
  1576. ;;      ?pg - generate begin and nested macros for current procedure
  1577. ;;
  1578. ;;      format:
  1579. ;;        ?pg n,p,c,a,w,nnu,cc
  1580. ;;      where:
  1581. ;;              n       is the name of the procedure
  1582. ;;              p       is the public flag
  1583. ;;              c       is the class definition for the procedure
  1584. ;;              a       is an enumerated list of registers to save
  1585. ;;                      at entry and restore at exit
  1586. ;;              w       true if a far windows procedure
  1587. ;;        nnu    procedure name without any underscore
  1588. ;;        cc    calling convention (C or PL/M)
  1589. ;;
  1590. ;;
  1591. ;;      local stack allocation will be forced to an even byte count to
  1592. ;;      maintain stack word alignment.
  1593.  
  1594. ?pg macro n,p,c,a,w,nnu,cc
  1595. .xcref
  1596. if ?uf
  1597. if ?nd
  1598. ??error <NODATA encountered in &n - user frame ignored>
  1599. ?uf=0
  1600. endif
  1601. endif
  1602. .xcref cBegin
  1603. cBegin macro g
  1604. .xcref
  1605. if cc
  1606. uconcat <?PLMParm>,%?PLMPrevParm,%?po
  1607. endif
  1608. if ?uf
  1609. if ?rp
  1610. ??error <parmR encountered in &n - user frame ignored>
  1611. ?uf=0
  1612. endif
  1613. endif
  1614. ?pg1 <n>,c,a,%?po,w,%?uf,%?nd,%?rp,cc
  1615. ?cpd=0
  1616. ?argc=0
  1617. ?ba=1
  1618. ???=(???+1) and 0fffeh
  1619. if p
  1620. public n
  1621. endif
  1622. ife c
  1623. n proc near
  1624. else
  1625. n proc far
  1626. endif
  1627. ife cc
  1628. nnu equ n
  1629. endif
  1630. ifidn <g>,<nogen>
  1631. if ???+?po+a+?rp
  1632. ??_out <cBegin - possible invalid use of nogen>
  1633. endif
  1634. else
  1635. if ?uf
  1636. ?mf c,%???,%?po
  1637. mpush a
  1638. else
  1639. if w
  1640. ife ?nd
  1641.     mov    ax,ds
  1642.     nop
  1643. endif
  1644. ife ?nx
  1645. ife ?DOS5
  1646.     inc    bp
  1647. endif
  1648.     push    bp
  1649.     mov    bp,sp
  1650.     push    ds
  1651. else
  1652. if ?ff+???+?po+?rp
  1653.     push    bp
  1654.     mov    bp,sp
  1655. endif
  1656. endif
  1657. ife ?nd
  1658.     mov    ds,ax
  1659. endif
  1660. else
  1661. if ?ff+???+?po+?rp
  1662.     push    bp
  1663.     mov    bp,sp
  1664. endif
  1665. endif
  1666. if ?rp
  1667. ?uf=0
  1668. rept ?rp
  1669. uconcat mpush,,?rp,%?uf
  1670. ?uf=?uf+1
  1671. endm
  1672. endif
  1673. if ???
  1674. if ?chkstk1
  1675. ifdef ?CHKSTKPROC
  1676. ?CHKSTKPROC %???
  1677. else
  1678.     mov    ax,???
  1679. ife cc
  1680.     call    _chkstk
  1681. else
  1682.     call    chkstk
  1683. endif
  1684. endif
  1685. else
  1686.     sub    sp,???
  1687. endif
  1688. endif
  1689. mpush a
  1690. endif
  1691. ifdef ?PROFILE
  1692. if c
  1693.     call    StartNMeas
  1694. endif
  1695. endif
  1696. endif
  1697. .cref
  1698. purge cBegin
  1699. endm
  1700. .xcref ?utpe
  1701. ?utpe macro
  1702. ??error <unterminated procedure definition: "&n">
  1703. endm
  1704. .cref
  1705. endm
  1706.  
  1707. ;;      ?pg1 - generate end macro for current procedure
  1708. ;;
  1709. ;;      format:
  1710. ;;        ?pg1 n,c,a,o,w,f,d,r,cc
  1711. ;;      where:
  1712. ;;              n       is the name of the procedure
  1713. ;;              c       is the class definition for the procedure
  1714. ;;              a       is an enumerated list of registers to save
  1715. ;;                      at entry and restore at exit
  1716. ;;              o       is the number of bytes of paramteres to remove at exit
  1717. ;;              w       true if a far windows procedure
  1718. ;;              f       is 1 if to use the user's makeframe procedure
  1719. ;;        d    is 1 if NODATA procedure
  1720. ;;              r       number of register parameters
  1721. ;;        cc    calling convention (C or PL/M)
  1722.  
  1723. ?pg1 macro n,c,a,o,w,f,d,r,cc
  1724. .xcref
  1725. .xcref cEnd
  1726. cEnd macro g
  1727. .xcref
  1728. ?ba=0
  1729. ifidn <g>,<nogen>
  1730. if o+a+r
  1731. ??_out <cEnd - possible invalid use of nogen>
  1732. endif
  1733. else
  1734. ifdef ?PROFILE
  1735. if c
  1736. call StopNMeas
  1737. endif
  1738. endif
  1739. mpop a
  1740. if f
  1741.     db    0c3h
  1742. else
  1743. if w
  1744. ife ?nx
  1745. if (?TF eq 0) or (???+?rp)
  1746.     lea    sp,(-2)[bp]
  1747. endif
  1748.     pop    ds
  1749.     pop    bp
  1750. ife ?DOS5
  1751.     dec    bp
  1752. endif
  1753. else
  1754. if (?TF eq 0) or (???+?rp)
  1755.     mov    sp,bp
  1756. endif
  1757. if ???+?po+?rp
  1758.     pop    bp
  1759. endif
  1760. endif
  1761. else
  1762. if ?ff+???+?po+?rp
  1763. if (?TF eq 0) or (???+?rp)
  1764.     mov    sp,bp
  1765. endif
  1766.     pop    bp
  1767. endif
  1768. endif
  1769. ife cc
  1770.     ret
  1771. else
  1772.     ret    o
  1773. endif
  1774. endif
  1775. endif
  1776. n endp
  1777. .cref
  1778. purge cEnd
  1779. endm
  1780. .cref
  1781. endm
  1782.  
  1783. ;    assumes is a macro that will set up the assumes for a segment
  1784. ;    or group created with the createSeg macro.  If the assumed
  1785. ;    value passed in isn't known, then a normal assume is made.
  1786. ;
  1787. ;       usage:
  1788. ;               assumes s,g
  1789. ;
  1790. ;       where:
  1791. ;               s       is the register to make the assumption about
  1792. ;               g       is the value to assume is in it
  1793.  
  1794. assumes macro s,ln
  1795. ifdef MS_STARTUP
  1796. ifidn <code>,<ln>
  1797. assume s&:_TEXT
  1798. exitm
  1799. elseifidn <CODE>,<ln>
  1800. assume s&:_TEXT
  1801. exitm
  1802. elseifidn <data>,<ln>
  1803. assume s&:dgroup
  1804. exitm
  1805. elseifidn <DATA>,<ln>
  1806. assume s&:dgroup
  1807. exitm
  1808. endif
  1809. endif
  1810. ifndef ln&_assumes
  1811. assume s:ln
  1812. else
  1813. ln&_assumes s
  1814. endif
  1815. endm
  1816.  
  1817. ;    createSeg is a macro that sets up a segment definition and
  1818. ;    a logical name for that segment.  The logical name can be
  1819. ;       used to enter the segment, but it cannot be used for anything
  1820. ;       else.
  1821. ;
  1822. ;       usage:
  1823. ;        createSeg n,ln,a,co,cl,grp
  1824. ;       where:
  1825. ;               n       is the physical name of the segment
  1826. ;               ln      is the name it is to be invoked by
  1827. ;               a       is the alignment, and is optional
  1828. ;               co      is the combine type, and is optional
  1829. ;               cl      is the class, and is optional
  1830. ;               grp     is the name of the group that contains this segment
  1831.  
  1832. createSeg macro n,ln,a,co,cl,grp
  1833. ifnb <cl>
  1834. n segment a co '&cl'
  1835. else
  1836. n segment a co
  1837. endif
  1838. n ends
  1839. ?cs1 <ln>,<n>
  1840. ifnb <grp>
  1841. grp group n
  1842. ?cs3 <ln>,<grp>
  1843. ln&OFFSET equ <offset grp:>
  1844. ln&BASE equ <grp>
  1845. else
  1846. ?cs3 <ln>,<n>
  1847. ln&OFFSET equ <offset>
  1848. ln&BASE equ <n>
  1849. endif
  1850. endm
  1851. addseg macro grp,seg
  1852. .xcref
  1853. .xcref grp&_add
  1854. .cref
  1855. grp&_add macro s
  1856. grp&_in <seg>,s
  1857. endm
  1858. .xcref
  1859. .xcref grp&_in
  1860. .cref
  1861. grp&_in macro sl,s
  1862. ifb <s>
  1863. grp group sl
  1864. else
  1865. grp&_add macro ns
  1866. grp&_in <sl,s>,ns
  1867. endm
  1868. endif
  1869. endm
  1870. endm
  1871. defgrp macro grp,ln
  1872. endm
  1873. ?cs1 macro ln,n
  1874. .xcref
  1875. .xcref ln&_sbegin
  1876. .cref
  1877. ln&_sbegin macro
  1878. ?cs2 <ln>,<n>
  1879. n segment
  1880. .xcref
  1881. .xcref ?mf
  1882. .cref
  1883. ?mf macro c,l,p
  1884. if c
  1885.     extrn    n&_FARFRAME:near
  1886.     call    n&_FARFRAME
  1887. else
  1888.     extrn    n&_NEARFRAME:near
  1889.     call    n&_NEARFRAME
  1890. endif
  1891.     db    l shr 1
  1892.     db    p shr 1
  1893. endm
  1894. endm
  1895. endm
  1896. ?cs2 macro ln,n
  1897. .xcref
  1898. .xcref sEnd
  1899. .cref
  1900. sEnd macro arg
  1901. n ends
  1902. purge ?mf
  1903. purge sEnd
  1904. endm
  1905. endm
  1906. ?cs3 macro ln,n
  1907. .xcref
  1908. .xcref ln&_assumes
  1909. .cref
  1910. ln&_assumes macro s
  1911. assume s:&n
  1912. endm
  1913. endm
  1914. .xcref
  1915. .xcref sBegin
  1916. .cref
  1917.  
  1918. ;    sBegin is the macro that opens up the definition of a segment.
  1919. ;    The segment must have already been defined with the createSeg
  1920. ;       macro.
  1921. ;
  1922. ;       usage:
  1923. ;        sBegin ln
  1924. ;
  1925. ;       where:
  1926. ;               ln      is the logical name given to the segment when
  1927. ;                       it was declared.
  1928.  
  1929. sBegin macro ln
  1930. ln&_sbegin
  1931. endm
  1932.  
  1933.   ;    Define all segments that will be used.    This will allow the
  1934.   ;    assume and groups to be set up at one given place, and also
  1935.   ;    allow quick changes to be made
  1936.   ;
  1937.   ;    createSeg name,logname,align,combine,class,group
  1938.  
  1939. ife ?DF
  1940. createSeg _TEXT,Code,word,public,CODE
  1941. ife ?nodata1
  1942. createSeg _DATA,Data,word,public,DATA,DGROUP
  1943. defgrp DGROUP,Data
  1944. endif
  1945. if ?chkstk1
  1946. ifndef ?CHKSTKPROC
  1947. externp <chkstk>
  1948. endif
  1949. endif
  1950. endif
  1951.  
  1952. ;       errnz exp - generate error message if expression isn't zero
  1953. ;
  1954. ;    The errnz will generate an error message if the expression "exp"
  1955. ;    does not evaluate to zero.  This macro is very useful for testing
  1956. ;       relationships between items, labels, and data that was coded into
  1957. ;       an application.
  1958. ;
  1959. ;                  errnz   <offset $ - offset label>   ;error if not at "label"
  1960. ;                  errnz   <eofflag and 00000001b>     ;eofflag must be bit 0
  1961. ;
  1962. ;    For expressions involving more than one token, the angle brackets
  1963. ;       must be used.
  1964. ;
  1965. ;    The macro is only evaluated on pass 2, so forward references may be
  1966. ;       used in the expression.
  1967.  
  1968. errnz macro x
  1969. ifnb <x>
  1970. .errnz (x),<x>
  1971. endif
  1972. endm
  1973. errnz1 macro x1,x2
  1974. = *errnz* x1 = x2
  1975. .err
  1976. endm
  1977.  
  1978. ;       errn$ label,exp - generate error message if label (exp) <> $
  1979. ;
  1980. ;    The errnz will generate an error message if the label and "exp"
  1981. ;       does not evaluate to the current value of the location counter.
  1982. ;    This macro is very useful for testing relationships between
  1983. ;       labels and the location counter that was coded into an application.
  1984. ;
  1985. ;       examples:  errn$   label        ;error if not at "label"
  1986. ;                  errn$   label,+3     ;error if not three bytes from "label"
  1987. ;                  errn$   label,-3     ;error if not three bytes past "label"
  1988. ;
  1989. ;    If no "exp" is given, it is the same as specifying 0
  1990. ;
  1991. ;    The macro is only evaluated on pass 2, so forward references may be
  1992. ;       used in the expression.
  1993.  
  1994. errn$ macro l,x
  1995. errnz <offset $ - offset l x>
  1996. endm
  1997.  
  1998. ;;    If profile has been specified, declare the profile routines
  1999. ;;    to be external and far.  It would be best if this could be done
  2000. ;;    when the call is actually made, but then the fix-up would be
  2001. ;;    generated as segment-relative.
  2002.  
  2003. ifdef ?PROFILE
  2004. externFP <StartNMeas,StopNMeas>
  2005. endif
  2006.  
  2007. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2008.  
  2009.  
  2010. ; Extra macros for the c-runtime package
  2011. ;
  2012. ; Macro for calling another run-time-library function.
  2013. ; Does a PUSH CS/CALL NEAR in compact/large models, except
  2014. ; for QuickC.        
  2015.  
  2016. callcrt MACRO funcname
  2017. ifdef _QC2
  2018. call funcname
  2019. else
  2020. if sizeC
  2021. push cs
  2022. call near ptr (funcname)
  2023. else
  2024. call funcname
  2025. endif
  2026. endif
  2027. ENDM
  2028. .cref
  2029.